//
// Created by limo on 2025/9/26.
//

#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
#include "connection.h"
#include "tcp_connection.h"

namespace net {
    using boost::asio::ip::tcp;
    class TcpClient : public std::enable_shared_from_this<TcpClient> {
    public:
        using Ptr = std::shared_ptr<TcpClient>;
        using ConnectionPtr = Connection::Ptr;
        using ConnectHandler = std::function<void(ConnectionPtr, const boost::system::error_code&)>;

        // 构造函数：Client 内部管理自己的 io_context
        TcpClient()
                : m_ioContext(),
                  m_socket(m_ioContext) {

        }

        // 析构函数：确保线程清理
        ~TcpClient() {
            stop();
        }

        /**
         * @brief 启动客户端I/O线程和事件循环。
         */
        void start() {
            // 启动 io_context 事件循环
            m_clientThread = std::thread([this] {
                // 使用 work_guard 确保 io_context 在没有连接时也能保持运行
                boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work(m_ioContext.get_executor());
                std::cout << "Client thread started." << std::endl;
                m_ioContext.run();
                std::cout << "Client thread stopped." << std::endl;
            });
        }

        /**
         * @brief 停止客户端I/O线程。
         */
        void stop() {
            m_ioContext.stop();
            if (m_clientThread.joinable()) {
                m_clientThread.join();
            }
            // 清理连接
            m_connection = nullptr;
        }

        /**
         * @brief 异步连接到目标服务器。
         */
        void connect(const std::string& host, unsigned short port, ConnectHandler handler) {
            // 确保异步操作的生命周期被管理
            auto self = shared_from_this();

            tcp::resolver resolver(m_ioContext);
            tcp::resolver::results_type endpoints;
            boost::system::error_code ec;

            try {
                // 同步调用 resolve。该操作会阻塞当前线程（主线程），
                // 直到解析完成或失败。
                endpoints = resolver.resolve(host, std::to_string(port), ec);
            } catch (const boost::system::system_error& e) {
                // 捕获同步调用可能抛出的异常，并将其转换为 error_code
                ec = e.code();
            }

            if (ec) {
                // 解析失败：直接在当前线程调用回调并返回
                std::cerr << "Sync Resolve Failed! Error: " << ec.message() << std::endl;
                if (handler) {
                    handler(nullptr, ec);
                }
                return;
            }

            // 异步连接到解析出的任一端点
            boost::asio::async_connect(m_socket, endpoints,
               [this, self, handler](boost::system::error_code ec, const tcp::endpoint& /* endpoint */) {
                   if (!ec) {
                       // 连接成功

                       // 关键步骤：创建 TcpConnection 实例来接管已连接的 socket
                       m_connection = std::make_shared<TcpConnection>(m_ioContext, std::move(m_socket));

                       // (确保新的 socket 绑定到 io_context_)
                       m_socket = tcp::socket(m_ioContext);

                       // 启动连接（开始异步读）
                       m_connection->start();
                       if (handler) {
                           handler(m_connection, ec);
                       }
                   } else {
                       // 连接失败
                       if (handler) {
                           handler(m_connection, ec);
                       }
                       // 失败后，必须重新构造 socket 才能再次尝试连接
                       m_socket = tcp::socket(m_ioContext);
                   }
               });


        }

        // 获取当前的连接对象
        ConnectionPtr getConnection() const {
            return m_connection;
        }
    private:
        boost::asio::io_context m_ioContext;
        tcp::socket m_socket; // 初始 socket 用于连接操作
        std::thread m_clientThread;
        ConnectionPtr m_connection; // 成功的连接将存储在这里
    };

} // net
